/* ---------------------------------------------------------------------------------------------
 *
 *            Capital Alliance Software Confidential Proprietary
 *            (c) Copyright CAS 201{x}, All Rights Reserved
 *                          www.pekall.com
 *
 * ----------------------------------------------------------------------------------------------
 */

package com.android.music.view;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.Scroller;

/**
 * groupview
 * 
 * @author LeiKang
 */
public class ViewDragableSpace extends ViewGroup {
    private Scroller mScroller;

    private VelocityTracker mVelocityTracker;

    private int mScrollX = 0;

    private int mCurrentScreen = 0;

    private float mLastMotionX;

    private static final String LOG_TAG = "ViewDragableSpace";

    private static final int SNAP_VELOCITY = 1000;

    private final static int TOUCH_STATE_REST = 0;

    private final static int TOUCH_STATE_SCROLLING = 1;

    private int mTouchState = TOUCH_STATE_REST;

    private int mTouchSlop = 0;

    private int oldValue = 0;

    public boolean isHuaDong = false;

    /* ===================== 监听currentScreen ======================== */
    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);

    public void setProperty(int newValue) {
        changeSupport.firePropertyChange("property", oldValue, newValue);
        oldValue = newValue;
    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        changeSupport.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        changeSupport.removePropertyChangeListener(l);
    }

    /* ===================== 监听currentScreen end======================== */

    public ViewDragableSpace(Context context) {
        super(context);
        init();
    }

    public ViewDragableSpace(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        Context localContext = getContext();
        AccelerateDecelerateInterpolator localAccelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
        Scroller localScroller = new Scroller(localContext, localAccelerateDecelerateInterpolator);
        mScroller = localScroller;
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
    }

    /**
     * 拦截所有触摸屏移动事件
     */
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        final int action = ev.getAction();
        if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) {
            return true;
        }
        final float x = ev.getX();
        switch (action) {
            case MotionEvent.ACTION_MOVE:
                final int xDiff = (int) Math.abs(x - mLastMotionX);
                boolean xMoved = xDiff > mTouchSlop;
                if (xMoved) {
                    mTouchState = TOUCH_STATE_SCROLLING;
                }
                break;

            case MotionEvent.ACTION_DOWN:
                mLastMotionX = x;
                mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
                break;

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                mTouchState = TOUCH_STATE_REST;
                break;
        }
        return mTouchState != TOUCH_STATE_REST;
    }

    private void checkRecircle() {
        final int count = getChildCount();
        if (mCurrentScreen == count - 1) {
            final View child = getChildAt(0);
            removeViewInLayout(child);
            mCurrentScreen--;
            addViewInLayout(child, -1, child.getLayoutParams());
            layoutChildren();
        } else if (mCurrentScreen == 0) {
            final View child = getChildAt(count - 1);
            removeViewInLayout(child);
            mCurrentScreen++;
            addViewInLayout(child, 0, child.getLayoutParams());
            layoutChildren();
        }
    }

    private void layoutChildren() {
        final int count = getChildCount();

        final int width = getWidth();
        final int height = getHeight();

        int startX = 0;
        for (int i = 0; i < count; i++) {
            getChildAt(i).layout(startX, 0, startX + width, height);
            startX += width;
        }
        setScreen(mCurrentScreen);
    }

    public void setScreen(int screen) {
        if (screen >= 0 && screen < getChildCount()) {
            mCurrentScreen = screen;
            scrollTo(mCurrentScreen * getWidth(), 0);
            invalidate();
        }
    }

    public void setScreenId(int screenId) {
        for (int i = 0; i < getChildCount(); i++) {
            if (getChildAt(i).getId() == screenId)
                setScreen(i);
        }
    }

    private double ads;// touch初始位置

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);

        final int action = event.getAction();
        final float x = event.getX();

        double flag = 0;

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                mLastMotionX = x;
                ads = x;
                isHuaDong = true;
                break;
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(ads - x) > 30)
                    flag = 1.2;
                else
                    flag = 0.0;

                final int deltaX = (int) (flag * (mLastMotionX - x));
                mLastMotionX = x;

                if (deltaX < 0) {
                    if (mScrollX > 0) {
                        scrollBy(Math.max(-mScrollX, deltaX), 0);
                    } else {
                        checkRecircle();
                    }
                } else if (deltaX > 0) {
                    final int availableToScroll = getChildAt(getChildCount() - 1).getRight()
                            - mScrollX - getWidth();
                    if (availableToScroll > 0) {
                        scrollBy(Math.min(availableToScroll, deltaX), 0);
                    } else {
                        checkRecircle();
                    }
                }
                isHuaDong = true;
                break;
            case MotionEvent.ACTION_UP:
                Log.i(LOG_TAG, "event : up");
                final VelocityTracker velocityTracker = mVelocityTracker;
                velocityTracker.computeCurrentVelocity(1000);
                int velocityX = (int) velocityTracker.getXVelocity();

                if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
                    snapToScreen(mCurrentScreen - 1);
                } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
                    snapToScreen(mCurrentScreen + 1);
                } else {
                    snapToDestination();
                }

                if (mVelocityTracker != null) {
                    mVelocityTracker.recycle();
                    mVelocityTracker = null;
                }
                mTouchState = TOUCH_STATE_REST;
                setProperty(getChildAt(mCurrentScreen).getId());
                isHuaDong = false;
                break;
            case MotionEvent.ACTION_CANCEL:
                Log.i(LOG_TAG, "event : cancel");
                isHuaDong = false;
                mTouchState = TOUCH_STATE_REST;
        }
        mScrollX = this.getScrollX();

        return true;
    }

    private void snapToDestination() {
        final int screenWidth = getWidth();
        final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
        snapToScreen(whichScreen);
    }

    public void snapToScreen(int whichScreen) {
        Log.i(LOG_TAG, "snap To Screen " + whichScreen);
        mCurrentScreen = whichScreen;
        final int newX = whichScreen * getWidth();
        final int delta = newX - mScrollX;
        mScroller.startScroll(mScrollX, 0, delta, 0, Math.abs(delta) * 2);
        invalidate();
    }

    public void setToScreen(int whichScreen) {
        Log.i(LOG_TAG, "set To Screen " + whichScreen);
        mCurrentScreen = whichScreen;
        final int newX = whichScreen * getWidth();
        mScroller.startScroll(newX, 0, 0, 0, 10);
        invalidate();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childLeft = 0;

        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != View.GONE) {
                final int childWidth = child.getMeasuredWidth();
                child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
                childLeft += childWidth;
            }
        }

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        final int width = MeasureSpec.getSize(widthMeasureSpec);
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if (widthMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("error mode.");
        }
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("error mode.");
        }

        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            // System.out.println(getChildAt(i).getId() + "-----");
            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
        }
        // Log.i(LOG_TAG, "moving to screen " + mCurrentScreen);
        scrollTo(mCurrentScreen * width, 0);
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            mScrollX = mScroller.getCurrX();
            scrollTo(mScrollX, 0);
            postInvalidate();
        }
    }

    void enableChildrenCache() {
        boolean bool = true;
        int i = getChildCount();
        for (int j = 0;; ++j) {
            if (j >= i)
                return;
            View localView = getChildAt(j);
            localView.setDrawingCacheEnabled(bool);
            if (!(localView instanceof ViewGroup))
                continue;
            ((ViewGroup) localView).setAlwaysDrawnWithCacheEnabled(bool);
        }
    }
}
